package com.getan.boot.module.system.service.persistent;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.getan.boot.common.utils.Preconditions;
import com.getan.boot.jdbc.service.GenericService;
import com.getan.boot.module.system.constant.ErrorCode;
import com.getan.boot.module.system.entity.ConfigEntity;
import com.getan.boot.module.system.repository.ConfigRepository;
import com.getan.boot.module.system.service.cache.ConfigCacheService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 配置管理
 *
 * @author Bruce.Gong
 * @since 1.0.0-SNAPSHOT
 */
@Slf4j
@RequiredArgsConstructor
@Service
@Transactional(propagation = Propagation.SUPPORTS, rollbackFor = Exception.class)
public class ConfigService extends GenericService<ConfigRepository, ConfigEntity> {

    private final ConfigCacheService configCacheService;
    @Value(value = "${getan.cache.system.config:true}")
    private boolean useCache;

    /**
     * 根据配置编码查询配置值
     *
     * @param code 编码
     * @return 配置值
     */
    public ConfigEntity getByCode(String code) {
        if (useCache) {
            List<ConfigEntity> entities = configCacheService.cacheActive();
            return entities.stream()
                    .filter(v -> Objects.equals(code, v.getCode()))
                    .findFirst()
                    .orElse(null);
        } else {
            return getOne(Wrappers.<ConfigEntity>lambdaQuery()
                    .eq(ConfigEntity::getCode, code), true);
        }
    }

    /**
     * 校验部门名称是否唯一
     *
     * @param entity {id,pid,name}
     */
    public void checkCode(ConfigEntity entity) {
        Preconditions.check(() -> exists(Wrappers.<ConfigEntity>lambdaQuery()
                .eq(ConfigEntity::getCode, entity.getCode())), ErrorCode.CONFIG_CODE_EXISTS);
    }

    /**
     * 校验配置是否可用
     *
     * @param id 配置ID
     */
    private void checkExists(Long id) {
        ConfigEntity db = getById(id);
        Preconditions.isNull(db, ErrorCode.CONFIG_NOT_EXISTS);
    }

    /**
     * 检查是否存在
     *
     * @param ids 配置ID
     * @return 配置
     */
    private List<ConfigEntity> checkExists(List<Long> ids) {
        List<ConfigEntity> dbs = list(Wrappers.<ConfigEntity>lambdaQuery()
                .select(ConfigEntity::getId, ConfigEntity::getCode, ConfigEntity::getSys)
                .in(ConfigEntity::getId, ids));
        Preconditions.check(() -> dbs.size() != ids.size(), ErrorCode.CONFIG_NOT_EXISTS);
        return dbs;
    }

    /**
     * 检查是否系统配置
     *
     * @param dbs 配置
     */
    private void checkSystem(List<ConfigEntity> dbs) {
        List<String> sysCodes = dbs.stream()
                .filter(v -> Boolean.TRUE.equals(v.getSys()))
                .map(ConfigEntity::getCode)
                .collect(Collectors.toList());
        Preconditions.notEmpty(sysCodes, ErrorCode.CONFIG_IS_SYS, sysCodes);
    }

    public void canUpdate(Long id) {
        checkExists(id);
    }

    /**
     * 校验配置是否可用
     *
     * @param ids 配置ID
     */
    public void canDelete(List<Long> ids) {
        checkSystem(checkExists(ids));
    }

    public void removeCache() {
        try {
            if (useCache) {
                configCacheService.removeCache();
            }
        } catch (Exception e) {
            log.error("删除缓存失败[config]", e);
        }
    }

}
